﻿using System;
using System.ComponentModel.Composition;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
using EnvDTE;
using Microsoft.VisualStudio.CommandBars;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Windows.Forms;

namespace MSBuildEditor
{


    [Export(typeof(IVsTextViewCreationListener))]
    [Name("token completion handler")]
    [ContentType("xml")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal class MSBuildCompletionHandlerProvider : IVsTextViewCreationListener
    {
        [Import]
        internal IVsEditorAdaptersFactoryService AdapterService = null;
        [Import]
        internal ICompletionBroker CompletionBroker { get; set; }
        [Import]
        internal SVsServiceProvider ServiceProvider { get; set; }

        internal ITextView _textView;
        private string _fileName;

        public void VsTextViewCreated(IVsTextView textViewAdapter)
        {
            ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
            if (textView == null)
                return;

            textView.Closed += textView_Closed;
            textView.GotAggregateFocus += textView_GotAggregateFocus;
            textView.LostAggregateFocus += textView_LostAggregateFocus;

            Func<MSBuildCompletionCommandHandler> createCommandHandler = delegate() { return new MSBuildCompletionCommandHandler(textViewAdapter, textView, this); };
            textView.Properties.GetOrCreateSingletonProperty(createCommandHandler);

            _textView = textView;
            CommandBarButton compileButton = Utility.EnvDteUtil.GetMSBuildCommandBarButton(ServiceProvider);
        }

        void textView_LostAggregateFocus(object sender, EventArgs e)
        {
            ITextView tv = (ITextView)sender;
            _textView = tv;

            CommandBarButton compileButton = Utility.EnvDteUtil.GetMSBuildCommandBarButton(ServiceProvider);
            compileButton.Click -= compileButton_Click;

            CompletionData.ReservedProperties props = CompletionData.ReservedProperties.GetInstance();
            props.Clear();

        }

        void textView_GotAggregateFocus(object sender, EventArgs e)
        {
            ITextView tv = (ITextView)sender;
            _textView = tv;
            _fileName = Utility.TextViewUtil.GetFileName(tv);

            CommandBarButton compileButton = Utility.EnvDteUtil.GetMSBuildCommandBarButton(ServiceProvider);
            compileButton.Click += compileButton_Click;

            CompletionData.ReservedProperties props = CompletionData.ReservedProperties.GetInstance();
            props.CreateData(Utility.TextViewUtil.GetFileName(tv));
        }

        void textView_Closed(object sender, EventArgs e)
        {
            Utility.ErrorListManager.RemoveErrorTask(ServiceProvider, _fileName);
        }

        void compileButton_Click(CommandBarButton Ctrl, ref bool CancelDefault)
        {
            Utility.ErrorListManager.RemoveErrorTask(ServiceProvider, _fileName);

            int currentPosition = _textView.Caret.Position.BufferPosition.Position;
            SnapshotPoint rootSnapshotPoint = new SnapshotPoint(_textView.TextSnapshot, 0);
            SnapshotSpan allSpan = new SnapshotSpan(rootSnapshotPoint, _textView.TextSnapshot.Length);
            string allText = allSpan.GetText();
            Intellisense.SelectedTaskInfo info = Intellisense.SelectedDataGetter.GetSelectedTaskInfo(allText, _textView.Caret.Position.BufferPosition.Position);
            if (info == null)
                return;
            if (info.TaskName == "UsingTask" || info.ParentXPath.Contains("UsingTask"))
            {
                MatchCollection startMatches = Intellisense.MSBuildMatch.GetMatches(allText, "<UsingTask", 0);
                if (startMatches.Count <= 0)
                    return;
                int usingTaskStartPosition = 0;
                foreach (Match m in startMatches)
                {
                    if (m.Index <= currentPosition)
                        usingTaskStartPosition = m.Index;
                }
                MatchCollection endMatches = Intellisense.MSBuildMatch.GetMatches(allText, "</UsingTask>", usingTaskStartPosition);
                if (endMatches.Count <= 0)
                    return;
                int usingTaskEndPosition = endMatches[0].Index+endMatches[0].Length;

                SnapshotSpan usingTaskSpan = new SnapshotSpan(
                    new SnapshotPoint(_textView.TextSnapshot, usingTaskStartPosition),
                    new SnapshotPoint(_textView.TextSnapshot, usingTaskEndPosition));
                string usingTask = usingTaskSpan.GetText();

                List<string> message;
                bool compileResult = Compiler.InlineCodeCompiler.Compile(usingTask, out message);
                if (compileResult)
                    MessageBox.Show("Compilation is complete", "Compile result", MessageBoxButtons.OK, MessageBoxIcon.Information);
                else
                {
                    message.ForEach(m =>
                        Utility.ErrorListManager.AddErrorTask(
                            ServiceProvider,
                            _textView, usingTaskStartPosition,
                            Utility.ErrorCategory.Error,
                            Utility.TextViewUtil.GetFileName(_textView),
                            m));
                    Utility.ErrorListManager.ShowErrorList(ServiceProvider);
                }
            }
        }

    }
}
